package com.qf.controller;

import com.qf.annotation.RequiresPermissionsDesc;
import com.qf.service.GoodsProductService;
import com.qf.service.GoodsService;
import com.qf.service.OrderService;
import com.qf.service.UserService;
import com.qf.util.ResponseUtil;
import com.qf.vo.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.*;

@RestController
//跨域
@CrossOrigin("*")
@RequestMapping("/dashboard")
public class IndexController {
    @Autowired
    private UserService userService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private GoodsProductService productService;
    @Autowired
    private OrderService orderService;
    /**
     * 首页数据统计
     * 统计: User用户数, SPU商品数量, SKU货品刷领, Order订单数
     * @return
     */
    @GetMapping("")
    //具有管理员, 商品模块, 查询权限才可以访问
    @RequiresPermissions("admin:goods:list")
    //具有, 系统管理, 或者商品管理, 或者订单管理的查询权限, 才能够访问这个方法
    @RequiresPermissionsDesc(menu = {"系统管理", "商品管理", "订单管理"}, button = "查询")
    public Object dashboard(){
        //1. 统计用户数量
        int userCount = userService.countUser();
        //2. 统计商品数量
        int goodsCount = goodsService.countGoods();

        //3. 统计货品数量
        int productCount = productService.countGoodsProduct();

        //4. 统计订单数量
        int orderCount = orderService.countOrder();

        //5. 将统计的数据封装到map中, 返回
        Map<String,Object> data = new HashMap<>();
        data.put("userTotal",userCount);
        data.put("goodsTotal", goodsCount);
        data.put("productTotal", productCount);
        data.put("orderTotal", orderCount);
        return ResponseUtil.ok(data);

    }

    /**
     * 统计首页需要的图标数据返回
     * @return
     */
    @RequestMapping("/chart")
    public Object chart() {

        //1. 统计多少天内的用户增长量
        List<DayStatis> userCount = userService.incrCount();

        //2. 统计多少天内的商品销售额和销售数量
        List<DayStatis> goodsCount = orderService.incrCount();

        //3. 根据分类统计每个分类的商品销售额
        List<CategorySellAmts> categoryCount = orderService.categoryCount();
        CategorySellVo categorySellVo = fetchCategorySell(categoryCount);

        //4. 合并两个统计结果中的日期数据
        String[] dayData = unionDayData(userCount, goodsCount);
        //转换并合并统计数据, 需要合并日期, 用户数据, 订单数据
        UserOrderCntVo userOrderVo = new UserOrderCntVo();
        //用户数据, 合并日期和用户数据统计结果
        userOrderVo.setUserCnt(fetchArrayCnt(dayData, userCount));
        //订单数据, 合并日期和订单数据统计结果
        userOrderVo.setOrderCnt(fetchArrayCnt(dayData, goodsCount));
        //日期数据
        userOrderVo.setDayData(dayData);

        //转换统计结果为前端需要的, 日期, 订单数量, 订单金额数据
        OrderAmtsVo orderAmtsVo = fetchOrderAmtVo(goodsCount);

        //4. 封装到map中
        Map<String, Object> data = new HashMap<>();
        data.put("categorySell", categorySellVo);
        data.put("orderAmts", orderAmtsVo);
        data.put("userOrderCnt", userOrderVo);

        return ResponseUtil.ok(data);
    }

    /**
     * 补全日期数据
     */
    private String[] unionDayData(List<DayStatis> userCount, List<DayStatis> goodsCount) {
        Set<String> days = new HashSet<>();

        //将用户的日期数据, 放入set集合中
        for (DayStatis dayStatis : userCount) {
            days.add(dayStatis.getDayStr());
        }

        for (DayStatis dayStatis : goodsCount) {
            days.add(dayStatis.getDayStr());
        }

        //将set中日期数据过滤重复后, 放入list集合中
        List<String> list = new ArrayList<>(days);
        //对日期数据进行排序
        Collections.sort(list);

        //将list集合转换成数组返回
        return list.toArray(new String[0]);
    }

    /**
     * 统计集合中获取的订单数量, 用户数量, 如果对应日期没有统计的数据, 则设置为0
     * @param dayData
     * @param dayStatisCnts
     * @return
     */
    private int[] fetchArrayCnt(String[] dayData, List<DayStatis> dayStatisCnts){
        //设置存放统计订单数量的数字, 和日期数组同样长度
        int[] arrCnts = new int[dayData.length];

        //遍历日期数组
        for(int i = 0; i< dayData.length; i++){
            //订单量, 默认为0
            int daycnt = 0;
            //当前循环出的日期字符串
            String DayStr = dayData[i];
            //遍历日期和订单统计的集合数据
            for (DayStatis dayStatisCnt : dayStatisCnts) {
                if (DayStr.equals(dayStatisCnt.getDayStr())) {
                    //如果数组中的日期和集合中的日期对应, 那么拿出对应的统计的订单量数据,
                    //赋值给上面声明的全局数组
                    daycnt = dayStatisCnt.getCnts();
                    //跳出循环
                    break;
                }
            }
            arrCnts[i] = daycnt;
        }
        return arrCnts;
    }

    /**
     * 统计封装订单的销售额和订单数量数据
     * @param orderCnts
     * @return
     */
    private OrderAmtsVo fetchOrderAmtVo(List<DayStatis> orderCnts){
        OrderAmtsVo vo = new OrderAmtsVo();

        //传入统计数据集合大小
        int size = 0;
        if(orderCnts != null && orderCnts.size() > 0 ) {
            size = orderCnts.size();
        }

        //用来存日期数据
        String[] dayData = new String[size];
        //用来存订单数量
        int[] orderData = new int[size];
        //用来存订单每天总金额
        BigDecimal[] moneyData = new BigDecimal[size];

        //遍历统计的集合数据, 获取日期, 订单数量, 订单金额
        for(int i = 0 ; i < size; i++) {
            dayData[i] = orderCnts.get(i).getDayStr();
            orderData[i] = orderCnts.get(i).getCnts();
            moneyData[i] = orderCnts.get(i).getAmts();
        }

        vo.setDayData(dayData);
        vo.setOrderCntData(orderData);
        vo.setOrderAmtData(moneyData);
        return vo;
    }

    /**
     * 封装前端需要的根据分类统计销售额实体数据
     * @param categoryCount
     * @return
     */
    private CategorySellVo fetchCategorySell(List<CategorySellAmts> categoryCount) {
        CategorySellVo vo = new CategorySellVo();
        if (categoryCount == null || categoryCount.size() == 0) {
            return vo;
        }

        String[] categoryNameArray = new String[categoryCount.size()];
        if (categoryCount != null) {
            for (int i=0; i< categoryCount.size(); i++) {
                //获取分类名字, 赋值给分类名字数组
                categoryNameArray[i] = categoryCount.get(i).getName();
            }
        }

        //分类名字数组
        vo.setCategoryNames(categoryNameArray);
        //分类名字和统计的金额数据
        vo.setCategorySellData(categoryCount);
        return vo;
    }




}
